#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/rcupdate.h>


struct counter {
    atomic_t val;
};

static struct task_struct *reader, *writer;
static struct counter *g_counter;
static int *shared_data = 0, state_flags = 0;

static int reader_thread(void *arg)
{
	int i;
	int val = 0;
	int *data = NULL;

    for (i = 0; i < 10 && !state_flags; i++) {
        /* Access the counter atomically */
        rcu_read_lock();
		data = rcu_dereference(shared_data);
        val = atomic_read(&g_counter->val);
        rcu_read_unlock();

        printk(KERN_INFO "Reader thread: val=%d shared_data:%d\n", val, *data);

        msleep(1);
    }

    return 0;
}

static int writer_thread(void *arg)
{
    int i;
	int *data = NULL;

    data = kmalloc(sizeof(int), GFP_KERNEL);
    if (!data) {
    	kfree(data);
        return -ENOMEM;
    }

    for (i = 0; i < 10 && !state_flags; i++) {
        int val = i + 1;

		*data = val;
		rcu_assign_pointer(shared_data, data);

        /* Update the counter atomically */
        atomic_set(&g_counter->val, val);

        printk(KERN_INFO "Writer thread: val=%d data:%d\n", val, *data);

        msleep(5);
    }
    kfree(data);

    return 0;
}

static int __init rcu_atomic_init(void)
{
    /* Allocate the counter */
    g_counter = kzalloc(sizeof(*g_counter), GFP_KERNEL);
    if (!g_counter)
        return -ENOMEM;

    /* Initialize the counter */
    atomic_set(&g_counter->val, 0);

    /* Create the reader and writer threads */
    reader = kthread_create(reader_thread, NULL, "rcu-reader");
    writer = kthread_create(writer_thread, NULL, "rcu-writer");
    if (IS_ERR(reader) || IS_ERR(writer)) {
        kfree(g_counter);
        return -EINVAL;
    }
	wake_up_process(writer);
	msleep(10);
	wake_up_process(reader);

    printk(KERN_INFO "RCU Atomic Example Initialized\n");
    return 0;
}

static void __exit rcu_atomic_exit(void)
{
    /* Free the counter */
    kfree(g_counter);
	state_flags = 1;

    printk(KERN_INFO "RCU Atomic Example Destroyed\n");
}

module_init(rcu_atomic_init);
module_exit(rcu_atomic_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
